#ifndef __CC_PORT__
#define __CC_PORT__
#include "cc_core.h"
#include "cc_mempool.h"
#include "cc_log.h"

#define PORT_NUM(x, y, z) ((((x) & 0xF) << 7) | (((y) & 0xF) << 3) | (((z) & 0xF)))

typedef enum
{
  CC_PORT_UNUSE = 0,
  CC_PORT_TEST1 = PORT_NUM(0, 0, 1),
  CC_PORT_TEST2,
  CC_PORT_TEST3,
  CC_PORT_TEST4,
  CC_PORT_EVENT_TEST1 = PORT_NUM(0, 1, 0),
  CC_PORT_EVENT_TEST2,
  CC_PORT_EVENT_TEST3,


  CC_PORT_AUTO_FEED_SERVO = PORT_NUM(0, 2, 0),
  CC_PORT_AUTO_FEED_SCALE,
  CC_PORT_AUTO_FEED_MQTT,
} e_cc_port;

typedef enum
{
  CC_PORT_STATE_UNKNOWN = -1,
  CC_PORT_STATE_UNINIT = 0,
  CC_PORT_STATE_INIT,
  CC_PORT_STATE_CONN,
  CC_PORT_STATE_DISCONN
} e_cc_port_state;

typedef void (*cc_notify_callback_t)(e_cc_port src_port_id, e_cc_port dst_port_id, const char* topic, void* msg);
typedef int (*cc_port_send_end_t)(int state, void* user_data);    // 数据包发送完成回调

struct cc_port_sub_list
{
  cc_list_node node;
  char topic[CC_CONFIG_MSG_TOPIC_MAX_LEN];
};

typedef struct cc_port
{
  e_cc_port port_id;
  e_cc_port_state state;
  cc_que_t rx_que;                  // 端口数据接收队列
  cc_mempool_t mem;                 // 端口内存池
  cc_notify_callback_t listener;    // 全局消息回调函数
  uint32_t data_size;               // 端口最大处理的字节数
  void* user_data;
  cc_list sublist_head;
  char name[CC_CONFIG_PORT_NAME_MAX_LEN];

}* cc_port_t;

typedef struct
{
  char* topic;
  char* data;
  uint8_t frame_type;    // 以后做握手用
} cc_port_msg_frame;

cc_port_t cc_port_init(e_cc_port id, const char* name, size_t msg_num, size_t msg_size);
cc_port_t cc_port_get(e_cc_port port_id);
cc_mnode_t cc_port_get_msg_node(cc_port_t port, uint32_t timeout);

// 点对点
int cc_port_send(cc_port_t port, e_cc_port target_id, cc_mnode_t node);
// 需要用户自己归还node
cc_mnode_t cc_port_recv(cc_port_t port);
cc_mnode_t cc_port_recv_time(cc_port_t port, uint32_t timeout);
// 不需要用户自己归还node
int cc_port_recv_listen_time(cc_port_t port, uint32_t timeout);
int cc_port_recv_listen(cc_port_t port);
// 一对多
int cc_port_publish(cc_port_t port, const char* topic, cc_mnode_t node);
int cc_port_broadcast(cc_port_t port, cc_mnode_t node);
int cc_port_listen(cc_port_t port, cc_notify_callback_t cb);

int cc_port_subsribe(cc_port_t port, const char* topic);
int cc_port_unsubsribe(cc_port_t port, const char* topic);
// 设置连接状态
int cc_port_set_state(cc_port_t port, e_cc_port_state state);
e_cc_port_state cc_port_get_st(cc_port_t port);
// 设置调用者
int cc_port_set_user(cc_port_t port, void* user_data);
void* cc_port_get_user(cc_port_t port);

int cc_set_send_end_cb(cc_mnode_t node, cc_port_send_end_t cb, void* user_data);
int cc_port_disconnect(cc_port_t port);
int cc_port_deinit(cc_port_t port);
#endif